package com.atung.merchant.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.atung.merchant.config.auth.AuthUserMangerContext;
import com.atung.merchant.dto.ExcelMenuEntity;
import com.atung.merchant.dto.RoomMenuInfo;
import com.atung.merchant.enums.MenuState;
import com.atung.merchant.enums.QueryMenuState;
import com.atung.merchant.mapper.BusMerchantMenuMapper;
import com.atung.merchant.mapper.BusMerchantMenuTypeMapper;
import com.atung.merchant.mapper.BusMerchantOrderMapper;
import com.atung.merchant.mapper.BusOrderMenuMapper;
import com.atung.merchant.po.BusMerchantMenu;
import com.atung.merchant.po.BusMerchantMenuType;
import com.atung.merchant.po.BusMerchantOrder;
import com.atung.merchant.po.BusOrderMenu;
import com.atung.merchant.result.ApiResult;
import com.atung.merchant.service.MenuService;
import com.atung.merchant.vo.*;
import com.atung.merchant.vo.query.QueryMenuListRequest;
import com.atung.merchant.vo.query.QueryMenuTypeRequest;
import com.atung.merchant.vo.save.SaveMenuRequest;
import com.atung.merchant.vo.save.SaveMenuTypeRequest;
import com.atung.merchant.vo.save.SaveOrderMenuRequest;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author Administrator
 */
@Service
public class MenuServiceImpl implements MenuService {
    @Resource
    private BusMerchantMenuMapper busMerchantMenuMapper;
    @Resource
    private BusMerchantMenuTypeMapper busMerchantMenuTypeMapper;
    @Resource
    private BusOrderMenuMapper busOrderMenuMapper;

    @Resource
    private BusMerchantOrderMapper busMerchantOrderMapper;

    @Override
    public List<MealMenuTypeResponse> getMealMenuTypeService(QueryMenuTypeRequest request) {

        List<MealMenuTypeResponse> menuTypeResponseList = new ArrayList<>();


        QueryWrapper<BusMerchantMenuType> queryWrapperBusMerchantMenuType = new QueryWrapper<>();
        queryWrapperBusMerchantMenuType.eq("merchant_id", AuthUserMangerContext.getMerchantId());
        queryWrapperBusMerchantMenuType.orderByDesc("creator_time");
        List<BusMerchantMenuType> busMerchantMenuTypes = busMerchantMenuTypeMapper.selectList(queryWrapperBusMerchantMenuType);
        MealMenuTypeResponse all = MealMenuTypeResponse.builder().id(null).name("全部").check(false)
                .value(busMerchantMenuTypes.size()).build();
        //菜单分类数据
        menuTypeResponseList = busMerchantMenuTypes.stream().map(item -> {
            Boolean check = false;
            if (Objects.nonNull(request.getMenuTypeId())) {
                check = request.getMenuTypeId().equals(item.getId()) ? true : false;
            } else {
                all.setCheck(true
                );
            }
            return MealMenuTypeResponse.builder().name(item.getName()).id(item.getId())
                    .value(0).check(check).build();
        }).collect(Collectors.toList());
        menuTypeResponseList.add(0, all);

        return menuTypeResponseList;
    }

    @Override
    public MenuInfoListResponse getOrderMenuListService(QueryMenuListRequest request) {
        Long menuTypeId = request.getMenuTypeId();

        AuthUserMangerContext.getMerchantId();
        QueryMenuState menuState = request.getMenuState();
        List<MenuInfoResponse> menuInfoResponses = new ArrayList<>();
        if (menuState.equals(QueryMenuState.ORDERING)) {
            QueryWrapper<BusMerchantMenu> queryWrapperBusMerchantMenu = new QueryWrapper<>();
            queryWrapperBusMerchantMenu.eq("merchant_id", AuthUserMangerContext.getMerchantId());
            //分类编号
            if (Objects.nonNull(menuTypeId)) {
                queryWrapperBusMerchantMenu.eq("menu_type_id", menuTypeId);
            }
            queryWrapperBusMerchantMenu.orderByDesc("creator_time");
            List<BusMerchantMenu> busMerchantMenus = busMerchantMenuMapper.selectList(queryWrapperBusMerchantMenu);
            menuInfoResponses = busMerchantMenus.stream().map(item -> {
                String menuType = "";
                BusMerchantMenuType busMerchantMenuType = busMerchantMenuTypeMapper.selectById(item.getMenuTypeId());
                if (Objects.nonNull(busMerchantMenuType)) {
                    menuType = busMerchantMenuType.getName();
                }
                return MenuInfoResponse.builder()
                        .id(item.getId())
                        .unit(item.getUnit())
                        .name(item.getName())
                        .menuPrice(item.getPrice())
                        .menuTypeName(menuType)
                        .build();
            }).collect(Collectors.toList());

        } else {
            QueryWrapper<BusOrderMenu> queryWrapperBusOrderMenu = new QueryWrapper<>();
            queryWrapperBusOrderMenu.eq("order_id", request.getOrderId());
            if (Objects.nonNull(menuTypeId)) {
                queryWrapperBusOrderMenu.eq("menu_type_id", menuTypeId);
            }
            queryWrapperBusOrderMenu.ne("menu_state", MenuState.CANCEL.ordinal());
            queryWrapperBusOrderMenu.orderByDesc("creator_time");
            List<BusOrderMenu> busOrderMenus = busOrderMenuMapper.selectList(queryWrapperBusOrderMenu);
            menuInfoResponses = busOrderMenus.stream().map(item -> {
                String menuType = "";
                BusMerchantMenuType busMerchantMenuType = busMerchantMenuTypeMapper.selectById(item.getMenuTypeId());
                if (Objects.nonNull(busMerchantMenuType)) {
                    menuType = busMerchantMenuType.getName();
                }
                return MenuInfoResponse.builder()
                        .id(item.getId())
                        .menuPrice(item.getMenuPrice())
                        .menuTypeName(menuType)
                        .unit(item.getUnit())
                        .name(item.getMenuName())
                        .menuState(MenuState.getMenuState(item.getMenuState()))
                        .build();
            }).collect(Collectors.toList());
        }

        return MenuInfoListResponse.builder()
                .menuInfoResponses(menuInfoResponses).build();
    }

    @Override
    public ApiResult saveMenuOrderService(SaveOrderMenuRequest request) {


        BusMerchantOrder busMerchantOrder = busMerchantOrderMapper.selectById(request.getOrderId());
        if (Objects.isNull(busMerchantOrder)) {
            return ApiResult.fail();
        }
        BusOrderMenu busOrderMenu = new BusOrderMenu();
        busOrderMenu.setRoomName(busMerchantOrder.getRoomName());
        busOrderMenu.setOrderId(busMerchantOrder.getId());
        busOrderMenu.setMerchantId(AuthUserMangerContext.getMerchantId());

        BusMerchantMenu busMerchantMenu = busMerchantMenuMapper.selectById(request.getMenuId());
        if (Objects.nonNull(busMerchantMenu)) {
            busOrderMenu.setMenuName(busMerchantMenu.getName());
            busOrderMenu.setMenuId(busMerchantMenu.getId());
            busOrderMenu.setMenuState(MenuState.AWAIT.ordinal());
            busOrderMenu.setMenuTypeId(busMerchantMenu.getMenuTypeId());
            busOrderMenu.setMenuPrice(busMerchantMenu.getPrice());
            busOrderMenu.setUnit(busMerchantMenu.getUnit());
            busOrderMenuMapper.insert(busOrderMenu);
            return ApiResult.ok();
        }

        return ApiResult.fail("数据报错失败");
    }

    @Override
    public ApiResult cancelMenuOrderService(IdRequest request) {
        BusOrderMenu busOrderMenu = busOrderMenuMapper.selectById(request.getId());
        if (Objects.isNull(busOrderMenu)) {
            return ApiResult.fail();
        }
        busOrderMenu.setMenuState(MenuState.CANCEL.ordinal());
        busOrderMenuMapper.updateById(busOrderMenu);

        return ApiResult.ok();
    }

    @Override
    public List<MenuInfoResponse> getMealOrderMenuDetailsList(QueryMenuListRequest request) {
        Long menuTypeId = request.getMenuTypeId();
        QueryMenuState menuState = request.getMenuState();
        List<MenuInfoResponse> menuInfoResponses = new ArrayList<>();
        if (menuState.equals(QueryMenuState.ORDERING)) {
            QueryWrapper<BusMerchantMenu> queryWrapperBusMerchantMenu = new QueryWrapper<>();
            queryWrapperBusMerchantMenu.eq("merchant_id", AuthUserMangerContext.getMerchantId());
            //分类编号
            if (Objects.nonNull(menuTypeId)) {
                queryWrapperBusMerchantMenu.eq("menu_type_id", menuTypeId);
            }
            queryWrapperBusMerchantMenu.orderByDesc("creator_time");
            List<BusMerchantMenu> busMerchantMenus = busMerchantMenuMapper.selectList(queryWrapperBusMerchantMenu);

            menuInfoResponses = busMerchantMenus.stream().map(item -> {
                return MenuInfoResponse.builder()
                        .id(item.getId())
                        .name(item.getName())
                        .menuPrice(item.getPrice())
                        .menuTypeName("").build();
            }).collect(Collectors.toList());

        } else {
            QueryWrapper<BusOrderMenu> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("order_id", request.getOrderId());
            if (Objects.nonNull(menuTypeId)) {
                queryWrapper.eq("menu_type_id", menuTypeId);
            }
            queryWrapper.orderByDesc("creator_time");
            List<BusOrderMenu> busOrderMenus = busOrderMenuMapper.selectList(queryWrapper);
            menuInfoResponses = busOrderMenus.stream().map(item -> {
                return MenuInfoResponse.builder()
                        .id(item.getId())
                        .menuPrice(item.getMenuPrice())
                        .menuTypeName("")
                        .name(item.getMenuName())
                        .menuState(MenuState.getMenuState(item.getMenuState()))
                        .build();
            }).collect(Collectors.toList());
        }
        return menuInfoResponses;
    }

    @Override
    public ApiResult servingMenuOrderService(IdRequest request) {

        BusOrderMenu busOrderMenu = busOrderMenuMapper.selectById(request.getId());
        if (Objects.isNull(busOrderMenu)) {
            return ApiResult.fail();
        }
        busOrderMenu.setMenuState(MenuState.COMPLETE.ordinal());
        busOrderMenuMapper.updateById(busOrderMenu);

        return ApiResult.ok();
    }


    @Override
    @Transactional
    public Long saveMenuTypeService(SaveMenuTypeRequest saveMenuTypeRequest) {
        if (Objects.nonNull(saveMenuTypeRequest.getId())) {
            BusMerchantMenuType busMerchantMenuType = busMerchantMenuTypeMapper.selectById(saveMenuTypeRequest.getId());
            if (Objects.isNull(busMerchantMenuType)
                    &&
                    !AuthUserMangerContext.getMerchantId().equals(busMerchantMenuType.getMerchantId())) {
                throw new RuntimeException("");
            } else {
                busMerchantMenuType.setName(saveMenuTypeRequest.getName());
                busMerchantMenuTypeMapper.updateById(busMerchantMenuType);
                return busMerchantMenuType.getId();
            }
        }
        QueryWrapper<BusMerchantMenuType> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("merchant_id", AuthUserMangerContext.getMerchantId());
        queryWrapper.eq("name", saveMenuTypeRequest.getName());
        BusMerchantMenuType busMerchantMenuType1 = busMerchantMenuTypeMapper.selectOne(queryWrapper);
        if (Objects.isNull(busMerchantMenuType1)) {
            BusMerchantMenuType busMerchantMenuType = new BusMerchantMenuType();
            busMerchantMenuType.setMerchantId(AuthUserMangerContext.getMerchantId());
            busMerchantMenuType.setName(saveMenuTypeRequest.getName());
            busMerchantMenuTypeMapper.insert(busMerchantMenuType);
            return busMerchantMenuType.getId();
        }
        return busMerchantMenuType1.getId();
    }

    @Override
    public ApiResult deleteMenuTypeService(IdRequest idRequest) {
        BusMerchantMenuType busMerchantMenuType = busMerchantMenuTypeMapper.selectById(idRequest.getId());
        if (Objects.isNull(busMerchantMenuType)
                &&
                !AuthUserMangerContext.getMerchantId().equals(busMerchantMenuType.getMerchantId())
        ) {
            return ApiResult.fail();
        }
        busMerchantMenuTypeMapper.deleteById(idRequest.getId());
        return ApiResult.ok();

    }

    @Override
    public ApiResult deleteMenuService(IdRequest idRequest) {
        BusMerchantMenu busMerchantMenu = busMerchantMenuMapper.selectById(idRequest.getId());
        if (Objects.isNull(busMerchantMenu)
                ||
                !AuthUserMangerContext.getMerchantId().equals(busMerchantMenu.getMerchantId())
        ) {
            return ApiResult.fail("数据不存在");
        }
        busMerchantMenuMapper.deleteById(idRequest.getId());
        return ApiResult.ok();
    }

    @Override
    @Transactional
    public Long saveMenuService(SaveMenuRequest saveMenuRequest) {

        if (Objects.nonNull(saveMenuRequest.getId())) {
            BusMerchantMenu busMerchantMenu = busMerchantMenuMapper.selectById(saveMenuRequest.getId());
            if (Objects.isNull(busMerchantMenu)
                    &&
                    !AuthUserMangerContext.getMerchantId().equals(busMerchantMenu.getMerchantId())) {
                throw new RuntimeException();
            } else {
                BeanUtils.copyProperties(saveMenuRequest, busMerchantMenu);
                busMerchantMenuMapper.updateById(busMerchantMenu);
                return busMerchantMenu.getId();
            }
        }
        if (Objects.isNull(saveMenuRequest.getMenuTypeId())) {
            SaveMenuTypeRequest saveMenuTypeRequest = new SaveMenuTypeRequest();
            saveMenuTypeRequest.setName(saveMenuRequest.getMenuTypeName());
            Long menuTypeId = this.saveMenuTypeService(saveMenuTypeRequest);
            saveMenuRequest.setMenuTypeId(menuTypeId);
        }
        QueryWrapper<BusMerchantMenu> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("merchant_id", AuthUserMangerContext.getMerchantId());
        queryWrapper.eq("name", saveMenuRequest.getName());
        queryWrapper.eq("menu_type_id", saveMenuRequest.getMenuTypeId());
        BusMerchantMenu busMerchantMenuOne = busMerchantMenuMapper.selectOne(queryWrapper);
        if (Objects.nonNull(busMerchantMenuOne)) {
            busMerchantMenuOne.setPrice(saveMenuRequest.getPrice());
            busMerchantMenuMapper.updateById(busMerchantMenuOne);
            return busMerchantMenuOne.getId();
        }
        BusMerchantMenu busMerchantMenu = new BusMerchantMenu();
        BeanUtils.copyProperties(saveMenuRequest, busMerchantMenu);
        busMerchantMenu.setMerchantId(AuthUserMangerContext.getMerchantId());
        busMerchantMenu.setUnit(saveMenuRequest.getUnit());
        busMerchantMenuMapper.insert(busMerchantMenu);
        return busMerchantMenu.getId();
    }

    @Override
    @Transactional
    public ApiResult importExcelMenuService(MultipartFile file) throws IOException {
        QueryWrapper<BusMerchantMenuType> queryType = new QueryWrapper<>();
        queryType.eq("merchant_id", AuthUserMangerContext.getMerchantId());
        //获取所有分类
        List<BusMerchantMenuType> busMerchantMenuTypes = busMerchantMenuTypeMapper.selectList(queryType);
        List<SaveMenuTypeRequest> saveMenuTypeRequests = new ArrayList<>();
        Map<String, Long> busMerchantMenuTypeMap = busMerchantMenuTypes.stream()
                .collect(Collectors.toMap(
                        BusMerchantMenuType::getName,
                        entity -> entity.getId(),
                        (existing, replacement) -> existing // 保留现有的值
                ));
        List<ExcelMenuEntity> excelMenuEntityData = new ArrayList<>();
        EasyExcel.read(file.getInputStream(), ExcelMenuEntity.class, new AnalysisEventListener<ExcelMenuEntity>() {
            @Override
            public void invoke(ExcelMenuEntity data, AnalysisContext context) {
                if (Objects.isNull(data.getCategoryName())) {
                    return;
                }
                excelMenuEntityData.add(data);
            }

            @Override
            public void doAfterAllAnalysed(AnalysisContext context) {
                // 所有数据解析完成后的操作
                if (CollectionUtils.isEmpty(excelMenuEntityData)) {
                    return;
                }
                excelMenuEntityData.stream().map(ExcelMenuEntity::getCategoryName).collect(Collectors.toSet()).stream()
                        .filter(item -> !busMerchantMenuTypeMap.containsKey(item))
                        .forEach(item -> {
                            SaveMenuTypeRequest saveMenuTypeRequest = new SaveMenuTypeRequest();
                            saveMenuTypeRequest.setName(item);
                            saveMenuTypeRequests.add(saveMenuTypeRequest);
                        });

            }
        }).sheet().headRowNumber(2).doRead();

        // 新增分类
        saveMenuTypeRequests.stream().map(item -> {
                    try {
                        Long id = this.saveMenuTypeService(item);
                        if (Objects.nonNull(id)) {
                            busMerchantMenuTypeMap.put(item.getName(), id);
                            return null;
                        }
                    } catch (Exception e) {

                    }
                    return null;
                }).filter(Objects::nonNull) // 过滤掉所有null值
                .collect(Collectors.toList());
        //新增菜品

        List<SaveMenuRequest> saveMenuRequests = excelMenuEntityData.stream().map(item -> {
                    if (busMerchantMenuTypeMap.containsKey(item.getCategoryName())) {
                        // 如果map中包含key，则创建SaveMenuRequest对象并返回，否则返回null
                        return SaveMenuRequest.builder()
                                .price(BigDecimal.valueOf(item.getAmount()))
                                .menuTypeId(busMerchantMenuTypeMap.get(item.getCategoryName()))
                                .name(item.getName())
                                .build();
                    }
                    return null; // 如果不包含key，则返回null
                }).filter(Objects::nonNull) // 过滤掉所有null值
                .collect(Collectors.toList());
        List<Long> ids = saveMenuRequests.stream().map(this::saveMenuService).collect(Collectors.toList());
        return ApiResult.ok(ids);
    }

    @Override
    public List<ServingMenuOrderResponse> servingMenuOrderListService(Long id) {


         QueryWrapper<BusOrderMenu> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("merchant_id", AuthUserMangerContext.getMerchantId());
        queryWrapper.eq("menu_state", MenuState.AWAIT.ordinal());
        if(Objects.nonNull(id)){
            queryWrapper.eq("menu_type_id",id);
        }
        List<BusOrderMenu> busOrderMenus = busOrderMenuMapper.selectList(queryWrapper);

        // 使用Collectors.groupingBy来根据menuId分组
        Map<Long, List<RoomMenuInfo>> roomMenuInfoMap = busOrderMenus.stream()
                .collect(Collectors.groupingBy(
                        busOrderMenu -> busOrderMenu.getMenuId(), // 分组的键
                        Collectors.mapping( // 映射函数，将BusOrderMenu转换为RoomMenuInfo
                                busOrderMenu -> RoomMenuInfo.builder()
                                        .roomName(busOrderMenu.getRoomName())
                                        .creatorTime(busOrderMenu.getCreatorTime())
                                        .id(busOrderMenu.getId())
                                        .build(),
                                Collectors.toList() // 收集器，将映射结果收集成列表
                        )
                ));

        List<ServingMenuOrderResponse> uniqueServingMenuOrderResponse = busOrderMenus.stream()
                .collect(Collectors.toMap(BusOrderMenu::getMenuId, Function.identity(), (a, b) -> a))
                .values()
                .stream()
                .map(item -> {
                    return ServingMenuOrderResponse.builder()
                            .menuId(item.getMenuId())
                            .menuName(item.getMenuName())
                            .roomMenuInfo(roomMenuInfoMap.get(item.getMenuId()))
                            .menuCount(roomMenuInfoMap.get(item.getMenuId()).size())
                            .build();
                })
                .collect(Collectors.toList());
        return uniqueServingMenuOrderResponse;
    }

    @Override
    public ServingMenuOrderResponse servingMenuOrderDetailsService(Long id) {
        BusMerchantMenu busMerchantMenu = busMerchantMenuMapper.selectById(id);
        if(Objects.isNull(busMerchantMenu)){

            return null;
        }
        QueryWrapper<BusOrderMenu> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("merchant_id", AuthUserMangerContext.getMerchantId());
        queryWrapper.eq("menu_id", id);
        queryWrapper.eq("menu_state", MenuState.AWAIT.ordinal());
        List<BusOrderMenu> busOrderMenus = busOrderMenuMapper.selectList(queryWrapper);
        List<RoomMenuInfo> roomMenuInfo = busOrderMenus.stream()
                .map(
                        busOrderMenu -> {
                            return RoomMenuInfo.builder()
                                    .roomName(busOrderMenu.getRoomName())
                                    .creatorTime(busOrderMenu.getCreatorTime())
                                    .id(busOrderMenu.getId())
                                    .build();
                        }
                ).collect(Collectors.toList());
        return ServingMenuOrderResponse.builder()
                .menuId(id)
                .menuName(busMerchantMenu.getName())
                .roomMenuInfo(roomMenuInfo)
                .build();
    }


}
